<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>07_Storage-Storage工具封装</title>
  <!-- 
  在 JavaScript 中， `localStorage`  和  `sessionStorage`  是 Web Storage API 的一部分，用于在客户端存储数据。为了更方便地使用这两个存储工具，开发者通常会对它们进行封装，创建一个 Storage 工具类或模块。
  一、封装的目的

  1. 简化 API：通过封装，可以提供更简单易用的接口，减少重复代码。
  2. 统一管理：集中管理存储逻辑，便于维护和扩展。
  3. 增加功能：可以在封装中添加额外的功能，例如数据的序列化和反序列化、过期时间管理等。

  二、基本封装示例
  下面是一个简单的 Storage 工具封装示例，包括对  `localStorage`  和  `sessionStorage`  的基本操作。

   1. Storage 工具类
  class StorageUtil {
      constructor(storageType) {
          this.storage = storageType === 'session' ? sessionStorage : localStorage;
      }

      // 存储数据
      setItem(key, value) {
          this.storage.setItem(key, JSON.stringify(value));
      }

      // 获取数据
      getItem(key) {
          const value = this.storage.getItem(key);
          return value ? JSON.parse(value) : null;
      }

      // 删除数据
      removeItem(key) {
          this.storage.removeItem(key);
      }

      // 清空所有数据
      clear() {
          this.storage.clear();
      }

      // 检查是否存在某个键
      hasItem(key) {
          return this.storage.getItem(key) !== null;
      }
  }
   2. 使用示例
  // 使用 localStorage
  const localStorageUtil = new StorageUtil('local');
  localStorageUtil.setItem('username', '小明');
  console.log(localStorageUtil.getItem('username')); // 输出: 小明
  localStorageUtil.removeItem('username');

  // 使用 sessionStorage
  const sessionStorageUtil = new StorageUtil('session');
  sessionStorageUtil.setItem('sessionId', '123456');
  console.log(sessionStorageUtil.getItem('sessionId')); // 输出: 123456
  sessionStorageUtil.clear();
  三、封装的扩展功能

  1. 过期时间管理：可以在存储数据时添加过期时间，获取数据时检查是否过期。
  2. 数据加密：对存储的数据进行加密，增强安全性。
  3. 事件监听：可以实现数据变化时的事件监听，方便更新 UI。

   过期时间管理示例
  class ExpiringStorageUtil extends StorageUtil {
      setItem(key, value, expireInMinutes) {
          const data = {
              value: value,
              expiry: expireInMinutes ? Date.now() + expireInMinutes * 60 * 1000 : null,
          };
          this.storage.setItem(key, JSON.stringify(data));
      }

      getItem(key) {
          const data = JSON.parse(this.storage.getItem(key));
          if (!data) return null;

          if (data.expiry && Date.now() > data.expiry) {
              this.removeItem(key);
              return null;
          }
          return data.value;
      }
  }
  四、总结

  - 封装 Storage 工具：通过封装  `localStorage`  和  `sessionStorage` ，可以简化存储操作，提高代码的可读性和可维护性。
  - 扩展功能：可以根据需求添加额外的功能，如过期时间管理和数据加密，以满足特定的业务需求。
  - 使用方便：封装后的工具类使得数据存储和管理更加直观，降低了使用门槛。
  -->
</head>
<body>

  <script>
    class Cache {
      constructor(isLocal = true) {
        this.storage = isLocal ? localStorage : sessionStorage
      }

      setCache(key, value) {
        if (!value) {
          throw new Error('value is required')
        }

        this.storage.setItem(key, JSON.stringify(value))
      }

      getCache(key) {
        const result = this.storage.getItem(key)
        if (result) {
          return JSON.parse(result)
        }
      }

      removeCache(key) {
        this.storage.removeItem(key)
      }

      clear() {
        this.storage.clear()
      }

      hasCache(key) {
        return this.storage.getItem(key) !== null
      }
    }

    const localCache = new Cache()
    const sessionCache = new Cache(false)

  </script>

  <script>
    localCache.setCache('name', 'zhangsan')

    // storage不能存储对象，只能存储字符串
    const obj = {name: 'lisi', age: 18}

    sessionCache.setCache('obj', obj)
    console.log(sessionCache.getCache('obj'));
    
  </script>
  
</body>
</html>